<template>
  <div class="auth-select">
    <div class="auth-select__left">
      <div class="menu-header">
        <span class="title"> 系统界面权限 </span>
        <!-- <span> 已选{{ selectAllChildren.length }}项 </span> -->
      </div>
      <a-menu v-model:selectedKeys="selectedKeys" class="auth-menu" mode="inline">
        <template v-for="firstMenu in menuData" :key="firstMenu.id">
          <template v-if="!judgeMenuIsLastMenu(firstMenu)">
            <a-sub-menu :key="firstMenu.id">
              <template #title>
                <div class="text-box text-box--sub">
                  <span>{{ firstMenu.name }}</span>
                  <span>{{ firstMenu.selectChildIds?.length }}/{{ firstMenu.childIds?.length }}</span>
                </div>
              </template>
              <a-menu-item v-for="secondMenu in firstMenu.childList" :key="secondMenu.id">
                <div class="text-box">
                  <span>{{ secondMenu.name }}</span>
                  <span>{{ secondMenu.selectChildIds?.length }}/{{ secondMenu.childIds?.length }}</span>
                </div>
              </a-menu-item>
            </a-sub-menu>
          </template>
          <template v-else>
            <a-menu-item :key="firstMenu.id">
              <div class="text-box">
                <span>{{ firstMenu.name }}</span>
                <span>{{ firstMenu.selectChildIds?.length }}/{{ firstMenu.childIds?.length }}</span>
              </div>
            </a-menu-item>
          </template>
        </template>
      </a-menu>
      <div class="flex-1"></div>
      <div v-if="!readonly" class="menu-footer">
        <a-button class="mr-16" style="height: 34px" @click="checkAllHandle">全选</a-button>
        <a-button class="clearBtn" type="link" @click="unCheckAllHandle">清除</a-button>
      </div>
    </div>
    <div v-if="currentMenu" class="auth-select__right">
      <div class="right-header">
        <img src="@/assets/img/admin/layout-5-line.svg" alt="" />
        <div class="module-name">{{ currentMenu.name || ' 请选择模块' }}</div>
        <div class="flex-1"></div>
        <a-checkbox v-if="!readonly" :checked="checkAll" @change="onCheckAllChange" />
      </div>
      <a-checkbox-group v-model:value="checkBoxValue" class="my-checkbox-group" style="width: 100%">
        <template v-if="currentMenu.childList[0].menuType === 3">
          <div class="auth-list">
            <div v-for="authItem in currentMenu.childList" :key="authItem.id" class="auth-item">
              {{ authItem.name }}
              <a-checkbox :disabled="readonly" :value="authItem.id" />
            </div>
          </div>
        </template>
        <template v-else>
          <div v-for="moduleItem in currentMenu.childList" :key="moduleItem.id" class="auth-module">
            <div class="module-title">{{ moduleItem.name }}</div>
            <div v-for="authItem in moduleItem.childList" :key="authItem.id" class="auth-item">
              {{ authItem.name }}
              <a-checkbox :disabled="readonly" :value="authItem.id" />
            </div>
          </div>
        </template>
      </a-checkbox-group>
    </div>
  </div>
</template>

<script setup lang="ts">
  import { computed, ref, watch } from 'vue'

  import { MenuItem } from '../types'

  interface Props {
    menuData: MenuItem[]
    readonly?: boolean
  }

  const props = withDefaults(defineProps<Props>(), {
    menuData: () => [],
    readonly: false
  })

  /* TODO:菜单逻辑 */
  const menuDataFlatObj = ref<Record<string, MenuItem>>({}) // 扁平菜单
  const selectedKeys = ref<string[]>([]) //当前选中菜单的id
  const currentMenu = ref<MenuItem>() //当前选中菜单
  const checkAll = ref(false) //全选
  const checkBoxValue = ref<string[]>([])
  const selectAllChildren = computed(() => {
    try {
      return props.menuData.reduce((ids: string[], firstMenu) => [...ids, ...firstMenu.selectChildIds], [])
    } catch (error) {
      return []
    }
  }) //选择的所有权限的id集合

  // 监听当前菜单的选中值，进行全选及父级菜单选中个数的联动
  watch(checkBoxValue, checkIds => {
    if (!currentMenu.value) {
      return
    }

    // 同步当前菜单选中的id
    currentMenu.value.selectChildIds = checkIds

    // 同步当前菜单的父级菜单的id
    if (currentMenu.value.parentId !== '0') {
      const currentParentMenu = menuDataFlatObj.value[currentMenu.value.parentId]
      // 父级菜单除去当前菜单选中的id
      const otherSelectIds = currentParentMenu.selectChildIds.filter(id => !currentMenu.value?.childIds.includes(id))
      // 父级id= 父级除当前菜单其他id + 当前菜单选中id
      currentParentMenu.selectChildIds = [...otherSelectIds, ...checkIds]
    }
    const isCheckAll = checkIds.length === (currentMenu.value.childCount || 0)
    checkAll.value = isCheckAll
  })

  // 根据当前菜单选择项找到对应菜单，并进行多选赋值
  watch(
    selectedKeys,
    val => {
      if (val.length) {
        currentMenu.value = menuDataFlatObj.value[val[0]]
        checkBoxValue.value = currentMenu.value.selectChildIds
      }
    },
    {
      deep: true
    }
  )

  // 判断是否最后一级菜单
  const judgeMenuIsLastMenu = (menu: MenuItem) => {
    const bool = menu.menuType === 1 && menu.childList.length && menu.childList[0].menuType !== 1
    return bool
  }

  // 拍平菜单当做菜单字典
  const flatMenuData = (arr: MenuItem[]) => {
    arr.forEach(it => {
      if (it.menuType !== 1) {
        return
      }
      menuDataFlatObj.value[it.id] = it
      if (it.childCount > 0) {
        flatMenuData(it.childList)
      }
    })
  }

  //选中初始第一个菜单
  const setInitItem = () => {
    let firstLastMenu: MenuItem
    const menu = props.menuData[0]
    // 有子菜单则选中第一个子菜单，否则选中当前menu
    if (menu.childList.length && menu.childList[0].menuType === 1) {
      firstLastMenu = menu.childList[0]
    } else {
      firstLastMenu = menu
    }

    if (!firstLastMenu) {
      return
    }
    selectedKeys.value.push(firstLastMenu.id)
    currentMenu.value = firstLastMenu
  }

  const onCheckAllChange = () => {
    if (!currentMenu.value) {
      return
    }
    if (checkAll.value) {
      return (checkBoxValue.value = [])
    }
    checkBoxValue.value = currentMenu.value.childIds || []
  }

  // 全选
  const checkAllHandle = () => {
    for (const key in menuDataFlatObj.value) {
      menuDataFlatObj.value[key].selectChildIds = menuDataFlatObj.value[key].childIds
    }
    checkBoxValue.value = menuDataFlatObj.value[selectedKeys.value[0]].selectChildIds
  }

  // 清除所有选择
  const unCheckAllHandle = () => {
    for (const key in menuDataFlatObj.value) {
      menuDataFlatObj.value[key].selectChildIds = []
    }
    checkBoxValue.value = []
  }

  // 初始化
  function init() {
    flatMenuData(props.menuData)
    setInitItem()
  }

  init()

  defineExpose({
    selectAllChildren
  })
</script>

<style lang="less" scoped>
  .auth-select {
    display: flex;
    height: 700px;
    border: 1px solid @border2;
    border-radius: 8px;

    .auth-select__left {
      display: flex;
      flex-direction: column;
      width: 275px;
      background: #fafafa;
      border-radius: 8px 0 0 8px;
      border-right: 1px solid #d9d9db;

      .menu-header {
        display: flex;
        justify-content: space-between;
        align-items: center;
        padding: 16px 24px 0 32px;
        .font14();

        color: @text02;

        .title {
          color: @text01;
          .font14b();
        }
      }

      .auth-menu {
        margin-top: 8px;
        width: 100%;
        background: transparent;
        border: none;

        .text-box {
          display: flex;
          justify-content: space-between;
          align-items: center;
          padding-left: 12px;
          width: 206px;
        }

        & > :deep(li:nth-of-type(n + 1)) {
          margin-top: 16px !important;
          margin-bottom: 16px !important;
        }

        :deep(.ant-menu-submenu) {
          .ant-menu-submenu-title {
            padding-right: 0 !important ;
            padding-left: 0 !important ;
            margin: 0 20px;
            width: auto;
            height: 32px;

            &:active,
            &:focus-visible {
              background: #e1e1e1;
              outline: none;
            }
          }

          .ant-menu-submenu-arrow {
            // transform: translate(16px, -2px);
            margin-right: -16px;
          }
        }

        // 已选中的submenu下的标题
        :deep(.ant-menu-submenu-selected > .ant-menu-submenu-title) {
          color: @text01;
        }

        :deep(.ant-menu-inline) {
          padding: 8px 0;
          margin-top: 8px;
          background: #f5f5f5;
        }

        :deep(.ant-menu-item) {
          padding-left: 0 !important ;
          margin-right: 20px;
          margin-left: 20px;
          width: auto;
          height: 32px;
          color: @text02;
          border-radius: 6px;
          .font14();

          &.ant-menu-item-selected {
            color: @text01;
            background: #e1e1e1;
            .font14();
          }
        }
      }

      .menu-footer {
        display: flex;
        padding: 16px 20px;
        width: 275px;

        .clearBtn {
          color: rgba(214, 24, 96, 1);
        }
      }
    }

    .auth-select__right {
      flex: 1;
      display: flex;
      flex-direction: column;

      .right-header {
        display: flex;
        align-items: center;
        padding: 0 32px 0 16px;
        height: 54px;
        min-height: 54px;
        background: #f5f5f5;
        border-radius: 0 8px 0 0;

        .icon {
          font-size: 16px;
          transform: translateY(1px);
          color: @text03;
        }

        .module-name {
          margin-left: 8px;
          color: @text01;
          .font14b();
        }

        img {
          width: 20px;
          height: 20px;
        }
      }

      .my-checkbox-group {
        display: flex;
        flex-flow: column nowrap;
        overflow-y: auto;
        padding: 16px 0;
        background-color: #fff;
        border-radius: 0 0 8px;
        flex: 1;

        .auth-module {
          border-bottom: 1px solid #e8e8eb;
          padding: 0 16px 16px;

          & + .auth-module {
            margin-top: 16px;
          }

          .module-title {
            display: flex;
            justify-content: space-between;
            padding-left: 36px;
            margin-bottom: 8px;
            width: 100%;
            height: 22px;
            color: @text02;
            background: rgba(25, 25, 48, 0.05);
            border-radius: 4px;
            .font14b();
          }
        }

        .auth-item {
          display: flex;
          justify-content: space-between;
          align-items: center;
          padding-left: 36px;
          width: 100%;
          height: 22px;

          & + .auth-item {
            margin-top: 16px;
          }
        }

        .auth-list {
          padding: 0 32px 16px 16px;
          width: 100%;
        }
      }
    }
  }
</style>
